package org.marverse.scripting

import com.google.common.base.ReferenceType
import com.google.common.collect.ReferenceMap
import ScriptingUtil._
import util.Util._

/**
 * Base for types that are really just java classes - primitive types.
 */
abstract case class JavaType[T](val javaClass: Class[T]) extends Type {
  override def isAssignableFrom(that: Type, ctx: MutableTypedMap[TypedKey, Any]) = 
    that match {
      case JavaType(thatClass) => javaClass.isAssignableFrom(thatClass)
      case _ => super.isAssignableFrom(that, ctx)
    }
}

/**
 * Representation of the {@link String} class as {@link Type}.
 */
object TextType extends JavaType(classOf[String]) {
  override def toString = "text"
  override def memberDeclarations = List(
    ValueMember('length, this, NumberType, _.asInstanceOf[String].length),
    UnaryMember('concat, this, this, this, (v1: Any, v2: Any) => 
      v1.asInstanceOf[String] + v2.asInstanceOf[String])
  )
  override def isInstance(value: Any) = value.isInstanceOf[String]
}

/**
 * Representation of the {@link Boolean} class as {@link Type}.
 */
object TruthType extends JavaType(classOf[Boolean]) {
  override def toString = "truth"
  override def memberDeclarations = List(
    UnaryMember('and, this, this, this, (v1: Any, v2: Any) => 
      v1.asInstanceOf[Boolean] && v2.asInstanceOf[Boolean]),
    UnaryMember('or, this, this, this, (v1: Any, v2: Any) => 
      v1.asInstanceOf[Boolean] || v2.asInstanceOf[Boolean]),
    ValueMember('not, this, this, !_.asInstanceOf[Boolean])
  )
  override def isInstance(value: Any) = value.isInstanceOf[Boolean]
}
 
/**
 * Representation of the {@link Double} class as {@link Type}.
 */
object NumberType extends JavaType(classOf[Double]) {
  override def toString = "number"
  override def memberDeclarations = List(
    UnaryMember('plus, this, this, this, (v1: Any, v2: Any) => 
      v1.asInstanceOf[Double] + v2.asInstanceOf[Double]),
    UnaryMember('times, this, this, this, (v1: Any, v2: Any) => 
      v1.asInstanceOf[Double] * v2.asInstanceOf[Double]),
    ValueMember('negative, this, this, -_.asInstanceOf[Double]),
    ValueMember('inverse, this, this, 1.0 / _.asInstanceOf[Double])
  )
  override def isInstance(value: Any) = value.isInstanceOf[Double]
}

